# -*- coding: utf-8 -*-
# @Time : 2021/05/18
# @Author : ricky
# @File : ruoyivue.py
# @Software: vscode
"""
核心修改类 RuoYi-Vue版本
"""
import os
from core import base
from constant import ruoyivueconstant as const


class RuoYiVue(base.BaseCore):
    def start(self):
        self.rootpath = ''
        self.default_project_name = ''
        # 拼接根路径
        for pn in const.RUOYI_DEFAULT_PROJECT_DIR_NAME_TUPLE:
            rootpath = os.path.join(self.targetdir, pn)
            if os.path.exists(rootpath):
                self.rootpath = rootpath
                self.default_project_name = ''
                break

        assert len(
            self.rootpath) > 0, '没有找到要修改的根目录，当前模式只允许修改顶层目录为：' + '、'.join(
                const.RUOYI_DEFAULT_PROJECT_DIR_NAME_TUPLE) + '的项目'
        # 1.修改站点名称
        self.messagehandle('正在修改标题和修站点名称...')
        self.__alter_site_name_and_title()
        self.messagehandle('站点名称和标题修改完成!')
        # 2.修改包名和项目名
        self.messagehandle('正在修改包名和项目名...')
        self.__alter_package_name_and_project_name(self.rootpath)
        self.messagehandle('包名和项目名修改完成!')
        # 3.修改pom.xml文件
        self.messagehandle('正在修改pom.xml...')
        self.__alter_pom_xml()
        self.messagehandle('pom.xml修改完成!')
        # 4.修改目录结构
        self.messagehandle('正在修改目录结构...')
        self.__alter_project_dir()
        self.messagehandle('目录结构修改完成!')

        if len(self.exceptions) > 0:
            self.messagehandle('\r发现有异常信息')
            self.messagehandle('-------------------\n\r')
            for e in self.exceptions:
                self.messagehandle(e)
            self.messagehandle('\r----------------------')

    def __alter_site_name_and_title(self):
        """修改站点名称和网站标题"""
        ntuple = const.RUOYI_SITE_RESOURCES_PATH_TUPLE
        for item in ntuple:
            filepath = os.path.join(self.rootpath,
                                    item.replace('#', os.path.sep))
            if os.path.exists(filepath):
                try:
                    with open(filepath, 'r',
                              encoding=self.DEFAULT_ENCODING) as srcfile, open(
                                  '%s.bak' % filepath,
                                  'w',
                                  encoding=self.DEFAULT_ENCODING) as desfile:
                        for line in srcfile:
                            if '若依管理系统' in line:
                                line = line.replace('若依管理系统', self.sitename)
                            if '若依后台管理系统' in line:
                                line = line.replace('若依后台管理系统', self.sitename)
                            desfile.write(line)
                    # 移除旧文件
                    os.remove(filepath)
                    # 重命名备份文件为新文件
                    os.rename('%s.bak' % filepath, filepath)
                except Exception as err:
                    self.exceptionhandle(
                        '修改站点名称和网站标题异常\n修改文件：{}\n异常信息：{}'.format(
                            filepath, err))

    def __alter_package_name_and_project_name(self, rootpath):
        """修改包名和项目名称"""
        files = os.listdir(rootpath)
        for filename in files:
            filepath = os.path.join(rootpath, filename)
            if os.path.isdir(filepath):
                self.__alter_package_name_and_project_name(filepath)
            else:
                if filename.endswith('.java') or filename.endswith(
                        '.yml') or filename.endswith(
                            'Mapper.xml') or filename.endswith(
                                'logback.xml') or filename.endswith(
                                    '.vm') or filename.endswith(
                                        '.bat') or filename.endswith('.sh'):
                    try:
                        encoding = self.get_encoding(filename)
                        with open(filepath, 'r',
                                  encoding=encoding) as srcfile, open(
                                      '%s.bak' % filepath,
                                      'w',
                                      encoding=encoding) as desfile:
                            self.messagehandle('正在修改：' + filename)
                            for line in srcfile:
                                if const.RUOYI_DEFAULT_PACKAGE_NAME in line:
                                    line = line.replace(
                                        const.RUOYI_DEFAULT_PACKAGE_NAME,
                                        self.packagename)
                                if const.RUOYI_DEFAULT_PROJECT_NAME + '-' in line:
                                    line = line.replace(
                                        const.RUOYI_DEFAULT_PROJECT_NAME + '-',
                                        self.projectname + '-')
                                if self.configdict['config.enable'] == 'True':
                                    if filename.endswith('.yml'):
                                        line = self.__check_yml_config(
                                            line, filename)
                                desfile.write(line)
                        # 移除旧文件
                        os.remove(filepath)
                        # 重命名备份文件为新文件
                        os.rename('%s.bak' % filepath, filepath)
                    except Exception as err:
                        self.exceptionhandle(
                            '修改包名和项目名称异常\n修改文件：{}\n异常信息：{}'.format(
                                filepath, err))

    def __check_yml_config(self, line, filename):
        """
        检测yml配置文件

        参数:
            line (str): 行
            filename (str): 文件名
        """
        if 'localhost:3306/ry-vue' in line and filename == 'application-druid.yml':
            line = self.__alert_yml_config(line, 'mysql_ip_port_name')
        if 'username: root' in line and filename == 'application-druid.yml':
            line = self.__alert_yml_config(line, 'mysql_username')
        if 'password: password' in line and filename == 'application-druid.yml':
            line = self.__alert_yml_config(line, 'mysql_password')
        if 'host: localhost' in line and filename == 'application.yml':
            line = self.__alert_yml_config(line, 'redis_host')
        if 'port: 6379' in line and filename == 'application.yml':
            line = self.__alert_yml_config(line, 'redis_port')
        if 'password: \n' in line and filename == 'application.yml':
            line = self.__alert_yml_config(line, 'redis_password')
        return line

    def __alert_yml_config(self, line, type_):
        """
        修改yml配置文件

        参数:
            line (str): 行
            type_ (str): 修改类型
        """
        if type_ == 'mysql_ip_port_name':
            mysql_ip = self.configdict['database.ip']
            mysql_port = self.configdict['database.port']
            mysql_name = self.configdict['database.name']
            return line.replace('localhost:3306/ry-vue',
                                mysql_ip + ':' + mysql_port + '/' + mysql_name)
        if type_ == 'mysql_username':
            mysql_username = self.configdict['database.username']
            return line.replace('username: root',
                                'username: ' + mysql_username)
        if type_ == 'mysql_password':
            mysql_password = self.configdict['database.password']
            return line.replace('password: password',
                                'password: ' + mysql_password)
        if type_ == 'redis_host':
            redis_ip = self.configdict['redis.ip']
            return line.replace('host: localhost', 'host: ' + redis_ip)
        if type_ == 'redis_port':
            redis_port = self.configdict['redis.port']
            return line.replace('port: 6379', 'port: ' + redis_port)
        if type_ == 'redis_password':
            redis_password = self.configdict['redis.password']
            return line.replace('password: \n',
                                'password: ' + redis_password + '\n')
        return line

    def __alter_pom_xml(self):
        """修改项目pom.xml文件"""
        # 将最外层的文件夹添加到新的元组中
        ttuple = (self.default_project_name, )
        ntuple = ttuple + const.RUOYI_DEFAULT_MODULE_NAME_TUPLE
        for module_name in ntuple:
            pom_xml_file = ''
            # 如果元组内元素是项目名，文件路径需要特殊处理
            if module_name == self.default_project_name:
                pom_xml_file = os.path.join(self.rootpath, 'pom.xml')
            else:
                pom_xml_file = os.path.join(self.rootpath, module_name,
                                            'pom.xml')
            if not os.path.exists(pom_xml_file):
                continue
            try:
                with open(pom_xml_file, 'r',
                          encoding=self.DEFAULT_ENCODING) as xml_file, open(
                              '%s.bak' % pom_xml_file,
                              'w',
                              encoding=self.DEFAULT_ENCODING) as target_file:
                    self.messagehandle('正在修改：' + module_name + '/pom.xml')
                    for line in xml_file:
                        if const.RUOYI_DEFAULT_GROUP_ID in line and '<groupId>' in line:
                            line = line.replace(const.RUOYI_DEFAULT_GROUP_ID,
                                                self.groupid)
                        if const.RUOYI_DEFAULT_ARTIFACTID_PREFIX in line and '<artifactId>' in line:
                            line = line.replace(
                                const.RUOYI_DEFAULT_ARTIFACTID_PREFIX,
                                self.artifactid)
                        if module_name == self.default_project_name:
                            if '<name>' in line or '<module>' in line:
                                line = line.replace(
                                    const.RUOYI_DEFAULT_PROJECT_NAME,
                                    self.projectname)
                            if 'version>' in line:
                                line = line.replace(
                                    const.RUOYI_DEFAULT_ARTIFACTID_PREFIX,
                                    self.artifactid)
                            if 'description>' in line:
                                line = line.replace(
                                    const.RUOYI_DEFAULT_SITE_NAME,
                                    self.sitename)
                        target_file.write(line)
                # 移除旧文件
                os.remove(pom_xml_file)
                # 重命名备份文件为新文件
                os.rename('%s.bak' % pom_xml_file, pom_xml_file)
            except Exception as err:
                self.exceptionhandle(
                    '修改项目pom.xml文件异常\n修改文件：{}\n异常信息：{}'.format(
                        pom_xml_file, err))

    def __alter_project_dir(self):
        """修改目录名"""
        for module_name in const.RUOYI_DEFAULT_MODULE_NAME_TUPLE:
            if not os.path.exists(os.path.join(self.rootpath, module_name)):
                continue
            src_main_java_dir = os.path.join(self.rootpath, module_name,
                                             'src/main/java')
            # 如果没有找到源代码路径，结束本次循环
            if os.path.exists(src_main_java_dir):
                source_dir = os.path.join(
                    src_main_java_dir,
                    self.packagename.replace('.', os.path.sep))
                if not os.path.exists(source_dir):
                    os.makedirs(source_dir)
                self.move_dir(os.path.join(src_main_java_dir, 'com/ruoyi'),
                              source_dir)

                # 拷贝完目录后会删除掉之前的文件，但是目录没有删除，再次删除目录
                for root, dirs, files in os.walk(os.path.join(
                        src_main_java_dir, 'com/ruoyi'),
                                                 topdown=False):
                    if not os.listdir(root):
                        os.rmdir(root)
                # 删除com目录
                if not os.listdir(os.path.join(src_main_java_dir, 'com')):
                    os.rmdir(os.path.join(src_main_java_dir, 'com'))
                os.rename(
                    os.path.join(self.rootpath, module_name),
                    os.path.join(
                        self.rootpath,
                        self.projectname + '-' + module_name.split('-')[1]))
            else:
                os.rename(
                    os.path.join(self.rootpath, module_name),
                    os.path.join(
                        self.rootpath,
                        self.projectname + '-' + module_name.split('-')[1]))
            self.messagehandle('正在修改：' + module_name)
        os.rename(self.rootpath,
                  os.path.join(self.targetdir, self.projectdirname))
        self.messagehandle('正在修改：' + self.default_project_name)